/*
 * ExecutionProxy.c
 * Behavioral Attributed Automaton
 * @author Gregoire JACOB (gregoire.jacob@orange-ftgroup.com)
 * @date 14/05/2008
 * @version 2.2
 * Execution proxy parser automaton
 */

#include ".\Includes\BehaviorAutomata.h"


void initExecutionAutomata(){
	int start[3] = {0,0,0};
	long lstart[3] = {0,0,0};
	execution.automata = NULL;
	execution.nbnautomata = 0;
	execution.nbmaxautomata = 0;
	startAutomaton(&execution,'s',lstart,start);
}


void parseExeCreate(long argid, int argtype){
	char curnode;
	long curids[3]; int curtypes[3];
	long nextids[3] = {0,0,0}; int nextypes[3] = {0,0,0};
	int i, j, nb = execution.nbnautomata;
	//long * CombinationTableLv1;

	for(i=0;i<nb;i++){
		struct PARSED_AUTOMATON * aut = &execution.automata[i];
		//Recover the state of the automaton
		curnode = getCurrentState(aut);
		getCurrentAttributes(aut,curids,curtypes);
		switch(curnode){
			
			case 's': //Initial creation
				if(ExeObjectCombin[argid][argid]==1) break;
				//Checks semantic rules
				if(argtype==TYPE_PERM){
					//if(ExeObjectCombin[argid]!=0) break;
					//Create a waiting new automaton replacing the parsed one
					startAutomaton(&execution,'s',nextids,nextypes);
					//printf("New automaton by open\n");
					nbambiguous++;
					aut = &execution.automata[i]; //Update relocation
					//Progression toward the next node
					nextids[1] = argid;
					nextypes[1] = argtype;
					addNode(aut,'a',nextids,nextypes);
					ExeObjectCombin[argid][argid] = 1;
					//printf("[+] Reach a by create %d\n",curids[1]);
				}else if(argtype==TYPE_COM){
					/*CombinationTableLv1 = (long *)ExeObjectCombin[argid];
					if(CombinationTableLv1 && CombinationTableLv1[argid]==1) break;*/
					//Create a waiting new automaton replacing the parsed one
					startAutomaton(&execution,'s',nextids,nextypes);
					//printf("New automaton by open\n");
					nbambiguous++;
					aut = &execution.automata[i]; //Update relocation
					//Progression toward the next node
					nextids[0] = argid;
					nextypes[0] = argtype;
					addNode(aut,'b',nextids,nextypes);
					ExeObjectCombin[argid][argid] = 1;
					/*if(!CombinationTableLv1){
						ExeObjectCombin[argid] = (long)calloc(EOBJECTNB,sizeof(long));
						CombinationTableLv1 = (long *)ExeObjectCombin[argid];
					}
					CombinationTableLv1[argid] = 1;*/
					//printf("[+] Reach b by create %d\n",argid);
				}
				break;

			case 'a': //Already open target
				if(ExeObjectCombin[argid][curids[1]]==1) break;
				//Checks semantic rules
				if(argtype==TYPE_COM){
					/*CombinationTableLv1 = (long *)ExeObjectCombin[argid];
					if(CombinationTableLv1 && CombinationTableLv1[curids[1]]!=0) break;*/
					//Create a waiting new automaton replacing the parsed one
					startAutomaton(&execution,'a',curids,curtypes);
					//printf("New automaton by open\n");
					nbambiguous++;
					aut = &execution.automata[i]; //Update relocation
					//Progression toward the next node
					curids[0] = argid;
					curtypes[0] = argtype;
					addNode(aut,'c',curids,curtypes);
					ExeObjectCombin[argid][curids[1]] = 1;
					/*if(!CombinationTableLv1){
						ExeObjectCombin[argid] = (long)calloc(EOBJECTNB,sizeof(long));
						CombinationTableLv1 = (long *)ExeObjectCombin[argid];
					}
					CombinationTableLv1[curids[1]] = calloc(EOBJECTNB,sizeof(long));*/
					//printf("[+] Reach c by create: %d,%d \n",curids[0],curids[1]);
				}
				break;

			case 'b': //Already open interface
				if(ExeObjectCombin[curids[0]][argid]==1) break;
				//Checks semantic rules
				if(argtype==TYPE_PERM){
					/*CombinationTableLv1 = (long *)ExeObjectCombin[curids[0]];
					if(CombinationTableLv1[argid]!=0) break;*/
					//Create a waiting new automaton replacing the parsed one
					startAutomaton(&execution,'b',curids,curtypes);
					//printf("New automaton by open\n");
					nbambiguous++;
					aut = &execution.automata[i]; //Update relocation
					//Progression toward the next node
					curids[1] = argid;
					curtypes[1] = argtype;
					addNode(aut,'c',curids,curtypes);
					ExeObjectCombin[curids[0]][argid] = 1;
					for(j=0;j<EOBJECTNB;j++) ExeVariableCombin[curids[0]][j] = 0;
					//CombinationTableLv1[argid] = calloc(EOBJECTNB,sizeof(int));
					//printf("[+] Reach c by create: %d,%d \n",curids[0],curids[1]);
				}
				break;
		}//swithch
	}//for
}


void parseExeOpen(long argid, int argtype){
	char curnode;
	long curids[3]; int curtypes[3];
	long nextids[3] = {0,0,0}; int nextypes[3] = {0,0,0};
	int i, j, nb = execution.nbnautomata;
	//long * CombinationTableLv1;

	for(i=0;i<nb;i++){
		struct PARSED_AUTOMATON * aut = &execution.automata[i];
		//Recover the state of the automaton
		curnode = getCurrentState(aut);
		getCurrentAttributes(aut,curids,curtypes);
		switch(curnode){
			
			case 's': //Initial open
				if(ExeObjectCombin[argid][argid]==1) break;
				//Checks semantic rules
				if(argtype==TYPE_PERM){
					//if(ExeObjectCombin[argid]!=0) break;
					//Create a waiting new automaton replacing the parsed one
					startAutomaton(&execution,'s',nextids,nextypes);
					//printf("New automaton by open\n");
					nbambiguous++;
					aut = &execution.automata[i]; //Update relocation
					//Progression toward the next node
					nextids[1] = argid;
					nextypes[1] = argtype;
					addNode(aut,'a',nextids,nextypes);
					//ExeObjectCombin[argid] = 1;
					ExeObjectCombin[argid][argid] = 1;
					//printf("[+] Reach a by open %d\n",argid);
				}else if(argtype==TYPE_COM){
					/*CombinationTableLv1 = (long *)ExeObjectCombin[argid];
					if(CombinationTableLv1 && CombinationTableLv1[curids[1]]!=0) break;*/
					//Create a waiting new automaton replacing the parsed one
					startAutomaton(&execution,'s',nextids,nextypes);
					//printf("New automaton by open\n");
					nbambiguous++;
					aut = &execution.automata[i]; //Update relocation
					//Progression toward the next node
					nextids[0] = argid;
					nextypes[0] = argtype;
					addNode(aut,'b',nextids,nextypes);
					ExeObjectCombin[argid][argid] = 1;
					/*if(!CombinationTableLv1){
						ExeObjectCombin[argid] = (long)calloc(EOBJECTNB,sizeof(long));
						CombinationTableLv1 = (long *)ExeObjectCombin[argid];
					}
					CombinationTableLv1[argid] = 1;*/
					//printf("[+] Reach b by open %d\n",argid);
				}
				break;

			case 'a': //Already open target
				if(ExeObjectCombin[argid][curids[1]]==1) break;
				//Checks semantic rules
				if(argtype==TYPE_COM){
					/*CombinationTableLv1 = (long *)ExeObjectCombin[argid];
					if(CombinationTableLv1 && CombinationTableLv1[curids[1]]!=0) break;*/
					//Create a waiting new automaton replacing the parsed one
					startAutomaton(&execution,'a',curids,curtypes);
					//printf("New automaton by open\n");
					nbambiguous++;
					aut = &execution.automata[i]; //Update relocation
					//Progression toward the next node
					curids[0] = argid;
					curtypes[0] = argtype;
					addNode(aut,'c',curids,curtypes);
					ExeObjectCombin[argid][curids[1]] = 1;
					/*if(!CombinationTableLv1){
						ExeObjectCombin[argid] = (long)calloc(EOBJECTNB,sizeof(long));
						CombinationTableLv1 = (long *)ExeObjectCombin[argid];
					}
					CombinationTableLv1[curids[1]] = (long)calloc(EOBJECTNB,sizeof(long));*/
					//printf("[+] Reach c by open: %d,%d \n",curids[0],curids[1]);
				}
				break;

			case 'b': //Already open interface
				if(ExeObjectCombin[curids[0]][argid]==1) break;
				//Checks semantic rules
				if(argtype==TYPE_PERM){
					/*CombinationTableLv1 = (long *)ExeObjectCombin[curids[0]];
					if(CombinationTableLv1[argid]!=0) break;*/
					//Create a waiting new automaton replacing the parsed one
					startAutomaton(&execution,'b',curids,curtypes);
					//printf("New automaton by open\n");
					nbambiguous++;
					aut = &execution.automata[i]; //Update relocation
					//Progression toward the next node
					curids[1] = argid;
					curtypes[1] = argtype;
					addNode(aut,'c',curids,curtypes);
					ExeObjectCombin[curids[0]][argid] = 1;
					//Reset read variable for new object
					for(j=0;j<EOBJECTNB;j++) ExeVariableCombin[curids[0]][j] = 0;
					//CombinationTableLv1[argid] = calloc(EOBJECTNB,sizeof(int));
					//printf("[+] Reach c by open: %d,%d \n",curids[0],curids[1]);
				}
				break;

		}//swithch
	}//for
}

void parseExeClose(long argid, int argtype){
	char curnode;
	long curids[3]; int curtypes[3];
	int i, nb = execution.nbnautomata;
	//long * CombinationTableLv1;

	for(i=0;i<nb;i++){
		struct PARSED_AUTOMATON * aut = &execution.automata[i];
		//Recover the state of the automaton
		curnode = getCurrentState(aut);
		getCurrentAttributes(aut,curids,curtypes);
		switch(curnode){
			
			case 'a': //Initial open or create
				if(argid==curids[1]&&argtype==curtypes[1]){
					//Object is close before any duplication-related operation
					deleteAutomaton(&execution,i);
					i--; nb--;
					ExeObjectCombin[argid][argid] = 0;
					//ExeObjectCombin[argid] = 0;
				}
				break;

			case 'c':
			case 'd':
				if(argid==curids[1]&&argtype==curtypes[1]){
					//Object is close before any related operation
					deleteAutomaton(&execution,i);
					i--; nb--;
					ExeObjectCombin[curids[0]][argid] = 0;
					/*CombinationTableLv1 = (long *)ExeObjectCombin[curids[0]];
					CombinationTableLv1[argid] = 0;*/
				}
				break;
		}//swithch
	}//for
}

void parseExeRead(long arg1id, int arg1type, long arg2id, int arg2type){
	char curnode;
	long curids[3]; int curtypes[3];
	int i, nb = execution.nbnautomata;
	//long * CombinationTableLv1;
	//long * CombinationTableLv2;
	
	if(ExeVariableCombin[arg2id][arg1id]==1) return;
	for(i=0;i<nb;i++){
		struct PARSED_AUTOMATON * aut = &execution.automata[i];
		//Recover the state of the automaton
		curnode = getCurrentState(aut);
		getCurrentAttributes(aut,curids,curtypes);
		switch(curnode){

			case 'c': //Simple read
				/*CombinationTableLv1 = (long *)ExeObjectCombin[curids[0]];
				CombinationTableLv2 = (long *)CombinationTableLv1[curids[1]];
				if(CombinationTableLv2[arg1id]==1) break;*/
				//Checks semantic rules
				if(arg1type==TYPE_VAR && arg2type==TYPE_COM && arg2id==curids[0]){
					//Create a waiting new automaton replacing the parsed one
					startAutomaton(&execution,'c',curids,curtypes);
					//printf("New automaton by read\n");
					nbambiguous++;
					aut = &execution.automata[i]; //Update relocation
					//Progression toward the next node
					curids[2] = arg1id;
					curtypes[2] = arg1type;
					addNode(aut,'d',curids,curtypes);
					ExeVariableCombin[arg2id][arg1id] = 1;
					//CombinationTableLv2[arg1id] = 1;
					//printf("[+] Reach d by read: %d,%d,%d \n",curids[0],curids[1],curids[2]);
				}
				break;

		}//swithch
	}//for
}

void parseExeWrite(long arg1id, int arg1type, long arg2id, int arg2type){
	char curnode;
	long curids[3]; int curtypes[3];
	int final[3] = {0,0,0}; long lfinal[3] = {0,0,0};
	int i, nb = execution.nbnautomata;

	for(i=0;i<nb;i++){
		struct PARSED_AUTOMATON * aut = &execution.automata[i];
		//Recover the state of the automaton
		curnode = getCurrentState(aut);
		getCurrentAttributes(aut,curids,curtypes);
		switch(curnode){
			
			case 'd': //Simple write
				//Checks semantic rules
				if(arg1type==TYPE_VAR && arg1id==curids[2] &&
					arg2type==TYPE_PERM && arg2id==curids[1]){
					//Progression toward the next node
					addNode(aut,'e',curids,curtypes);
					//printf("[+] Reach e by write\n");
				}
				break;

		}//swithch
	}//for
}

void parseExeExecute(long argid, int argtype){
	char curnode;
	long curids[3]; int curtypes[3];
	int final[3] = {0,0,0}; long lfinal[3] = {0,0,0};
	int i, nb = execution.nbnautomata;

	for(i=0;i<nb;i++){
		struct PARSED_AUTOMATON * aut = &execution.automata[i];
		//Recover the state of the automaton
		curnode = getCurrentState(aut);
		getCurrentAttributes(aut,curids,curtypes);
		switch(curnode){
			
			case 'e': 
				//Checks semantic rules
				if(argid==curids[1]){
					//Progression toward the next node
					addNode(aut,'f',lfinal,final);
					printf("[+] Execution proxy has been detected "
						"between %s%d and %s%d through %s%d\n",typestr[curtypes[0]],
						curids[0],typestr[curtypes[1]],curids[1],typestr[curtypes[2]],curids[2]);
					storeBehaviorEntry(pf_BehDB,EXECUTIONPROXY_REF,1,
									   curids[0],curids[1],curids[2]);
				}
				break;

		}//swithch
	}//for
}

void parseExeAffect(long arg1id, int arg1type, long arg2id, int arg2type){
	char curnode;
	long curids[3]; int curtypes[3];
	int i, nb = execution.nbnautomata;
	//long * CombinationTableLv1;
	//long * CombinationTableLv2;

	for(i=0;i<nb;i++){
		struct PARSED_AUTOMATON * aut = &execution.automata[i];
		//Recover the state of the automaton
		curnode = getCurrentState(aut);
		getCurrentAttributes(aut,curids,curtypes);
		switch(curnode){
			
			case 'd': 
				//Checks semantic rules
				if(arg1type<=TYPE_VAR && arg2type==TYPE_VAR && arg2id==curids[2]){
					/*CombinationTableLv1 = (long *)ExeObjectCombin[curids[0]];
					CombinationTableLv2 = (long *)CombinationTableLv1[curids[1]];
					if(CombinationTableLv2[arg1id]==1) break;*/
					//Start a parallel automaton with new variable
					curids[2] = arg1id;
					startAutomaton(&execution,curnode,curids,curtypes);
					nbambiguous++;
					//CombinationTableLv2[arg1id] = 1;
					//printf("[+] Reach d by read: %d,%d,%d \n",curids[0],curids[1],curids[2]);
				}
				break;

		}//swithch
	}//for
}


void updateExecutionAutomata(unsigned long operation,
							   long arg1id, int arg1type,
							   long arg2id, int arg2type){

	switch(operation){
		case OP_CREA:
			parseExeCreate(arg1id,arg1type);
			break;
		case OP_OPEN:
			parseExeOpen(arg1id,arg1type);
			break;
		case OP_CLOS:
			parseExeClose(arg1id,arg1type);
			break;
		case OP_EXEC:
			parseExeExecute(arg1id,arg1type);
			break;
		case OP_READ:
			parseExeRead(arg1id,arg1type,arg2id,arg2type);
			break;
		case OP_WRITE:
			parseExeWrite(arg1id,arg1type,arg2id,arg2type);
			break;
		case OP_AFF:
			parseExeAffect(arg1id,arg1type,arg2id,arg2type);
			break;
		//default:
			//ignore operation
	}
}



